﻿//  Object类型:创建实例的方式有两种
//1.new
var person = new Object();
person.name = "Nick";
person.age = 23;

//2.对象字面量
var p = {
    name: "Nick",
    age: 23
};
//或者
var p2 = {
    "name": "Nick",
    "age": 23,
    5 : true
};
// 另外，使用对象字面量语法时，如果留空其花括号，则可以定义只包含默认属性和方法的对象：
var p3 = {};
p3.name = "Nick";
p3.age = 23;

function displayInfo(args) {
    var output = "";
    if (typeof args.name=="string") {
        output += "Name:" + args.name + "\n";
    }
    if (typeof args.name == "number") {
        output += "Age:" + args.name + "\n";
    }

    alert(output);
}

displayInfo({
    name:"Nick",
    age:23
});

displayInfo({
    name:"jack"
});

//js中除了点表示法，也可以使用方括号表示法来访问对象的属性
alert(person.name);
alert(person["name"]);

var prop = "name";
alert(person[prop]);
// 若属性名中包含会导致语法错误的字符，或者属性名使用的是关键字或保留字，也可以使用方括号表示法
alert(person["first name"]);

//  Array类型
// 每一项可以保存任何类型的数据，且数组大小可以动态调整
// 创建数组的基本方式有两种：1.数组构造函数，如下
var colors = new Array();
var a2 = new Array(20);// 创建一个包含20项的数组
var a3 = new Array("red", "blue", 23, true);
var a4 = new Array("nick"); // 创建一个包含1项，即字符串"nick"的数组
// 也可省略new
var a5 = Array(2);
var a6 = Array("nick");
//2. 数组字面量表示法
var car = ["bmw", "a6l", "h6", "jetta"]; //创建一个包含4个字符串的数组
var name = []; //创建一个空数组

alert(car[0]); //显示第一项
car[2] = "bora"; //修改第三项
car[4] = "qq"; //新增第五项
//数组的length，不是只读的。因此，通过设置这个属性可以从数组的末尾移除项或者向数组中添加新项
car.length = 3;
alert(car[3]); //undefined
car.length = 5;
alert(car[4]); //undefined
car[car.length] = "v3";// 在位置4添加一种车型
car[car.length] = "v5"; // 在位置5添加一种车型

// 检测数组
if (value instanceof Array) {
    // 对数组执行某些操作
}
if (Array.isArray(value)) {// 支持此方法的浏览器：IE9+ FF4+ Safari5+ Opera10.5+ Chrome
    // 对数组执行某些操作
}

var c = ["red", "blue", "green"];
alert(c.toString()); // red,blue,green
alert(c.valueOf()); // red,blue,green
alert(c); // red,blue,green
alert(c.join(",")); // red,blue,green
alert(c.join("||")); //red||blue||green
// 栈方法push(),pop()
var arr = new Array();
var count = arr.push("red", "green");
alert(count); //2
count = arr.push("black");
alert(count); //3
var item = arr.pop();
alert(item); //black
alert(arr.length); //2
// 队列方法shift(),unshift()
var arr2 = new Array();
var count2 = arr.push("red", "green");
alert(count2); //2
count2 = arr2.push("black");
alert(count2); //3
var item2 = arr.shift();
alert(item2); //red
alert(arr2.length); //2

var arr3 = new Array();
var count3 = arr3.unshift("red", "green");
alert(count3); //2
count3 = arr3.unshift("black");
alert(count3); //3
var item3 = arr3.pop();
alert(item3); //green
alert(arr3.length); //2
// 重排序方法
//REVERSE()
var v = [1, 2, 3, 4, 5];
alert(v.reverse()); // 5,4,3,2,1
//SORT() 会调用数组项的toString()方法，然后比较得到的字符串，以确定如何排序
var v2 = [0, 1, 5, 10, 15];
alert(v2.sort()); //0,1,10,15,5

function esc(value1,value2) {
    if (value1 < value2) {
        return -1;
    }
    else if (value1 == value2) {
        return 0;
    } else {
        return 1;
    }
}

function desc(value1, value2) {
    if (value1 < value2) {
        return 1;
    }
    else if (value1 == value2) {
        return 0;
    } else {
        return -1;
    }
}

function compare(value1,value2) {
    return value2 - value1;
}

alert(v2.esc()); // 0,1,5,10,15
alert(v2.desc()); // 15,10,5,1,0
//CONCAT()
var cc = ["red", "blue", "green"];
var dd = cc.concat("yellow", ["black", "brown"]);
alert(cc); //red,blue,green
alert(dd); // red,blue,green,yellow,black,brown
//SLICE()
var s = ["red", "blue", "green", "yellow", "purple"];
alert(s.slice(1)); //blue,green,yellow,purple
alert(s.slice(1, 4)); //blue,green,yellow
//SPLICE()
var sp = ["red", "green", "blue"];
var removed = sp.splice(0, 1); // 删除第一项
alert(sp); //green,blue
alert(removed); //red

removed = sp.splice(1, 0, "yellow", "purple"); //从位置1开始插入两项
alert(sp); //green,yellow,purple,blue
alert(removed); //空数组

removed = sp.slice(1, 1, "red", "orange"); //删除一项，插入两项
alert(sp);//green,red,orange,purple,blue
alert(removed);//yellow
//位置方法 INDEXOF(),LASTINDEXOF(),比较第一个参数与数组项的时候采用全等操作
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
alert(numbers.indexOf(4)); //3
alert(numbers.lastIndexOf(4)); //5
alert(numbers.indexOf(4,4)); //5
alert(numbers.lastIndexOf(4,4)); //3
var person = { name: "nick" };
var people = [{ name: "nick"}];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(people)); //0

// 迭代方法：
//every()：对数组中的每一项运行给定函数，如果该函数对每一项都返回true，则返回true
//filter()：对数组中的每一项运行给定函数，返回该函数会返回true的项组成的数组
//foreach()：对数组中的每一项运行给定函数，没有返回值
//map()：对数组中的每一项运行给定函数，返回每次函数调用的结果组成的数据
//some()：对数组中的每一项运行给定函数，如果该函数对每任一项都返回true，则返回true
var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var everyResult = nums.every(function(item, index, array) {
    return (item > 2);
});

alert(everyResult); //false

var someResult = nums.some(function(item, index, array) {
    return (item > 2);
});

alert(someResult); //true

var filterResult = nums.filter(function(item, index, array) {
    return (item > 2);
});

alert(filterResult); //[3,4,5,4,3]

var mapResult = nums.map(function() {
    return item * 2;
});

alert(mapResult); //[2,4,6,8,10,8,6,4,2]

var foreachResult = nums.forEach(function() {
    // do something...
});

//缩小方法：reduce()，reduceRight()
var values = [1, 2, 3, 4, 5];
var sum = values.reduce(function(pre,cur,index,array) {
    return prev + cur;
});

alert(sum); //15

var values = [1, 2, 3, 4, 5];
var sum = values.reduceRight(function (pre, cur, index, array) {
    return prev + cur;
});

alert(sum); //15

//  Date类型
var now = new Date();
alert(now); //Wed Apr 23 2014 13:38:32 GMT+0800
//Date.parse();//返回表示日期的毫秒数
//Date.UTC();//返回表示日期的毫秒数
var someDate = new Date("May 25,2004");
var sd = Date.parse("May 25,2004");
alert(someDate.toString() === new Date(sd).toString());//true

// GMT时间 2000年1月1日午夜零时
var y2k = new Date(Date.UTC(2000, 0));
// GMT时间 2005年5月5日下午5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
var start = Date.now();
//do something
var i = 0;
var count = 10000;
while (i<count) {
    i++;
}
var stop = Date.now();
alert(stop - start);
var d = new Date(Date.now());

alert(d.toDateString()); //Wed Apr 23 2014
alert(d.toTimeString()); //14:19:15 GMT+0800
alert(d.toLocalDateString());//error
alert(d.toLocalTimeString());//error
alert(d.toUTCString()); //Wed, 23 Apr 2014 06:20:07 GMT

alert(d.getDate());//23
alert(d.getTime()); //1398234054699
alert(d.getHours()); //14
alert(d.getminutes()); //24
alert(d.getSeconds()); //17
alert(d.getMilliseconds()); //731
//  RegExp类型
// var expression = /pattern/flags;
//flags:
//g:全局模式，即模式将被应用于所有字符串，而非在发现第一个匹配项时立即停止
//i:表示不区分大小写模式，即在确定匹配项时忽略模式与字符串的大小写
//m:多行模式，即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项
// 字面量定义
//匹配字符串中所有'at'的实例
var p = /at/g;
//匹配第一个bat 或cat，不区分大小写
var p2 = /[bc]at/i;
//匹配所有以at结尾的3个字符的组合，不区分大小写
var p3 = /.at/gi;
//匹配第一个[bc]at,不区分大小写
var p4 = /\[bc\]at/i;
//匹配所有.at，不区分大小写
var p5 = /\.at/gi;
//RegExp构造函数定义
var cp = new RegExp("at", "g");
var cp2 = new RegExp("[bc]at", "i");
var cp3 = new RegExp(".at", "gi");
var cp4 = new RegExp("\\[bc\\]at", "i");
var cp5 = new RegExp("\\.at", "gi");

alert(cp4.global);//false
alert(cp4.ignoreCase);//true
alert(cp4.multiline);//false
alert(cp4.lastIndex);//0
alert(cp4.source); // "\[bc\]at"

// exec()方法，test()方法

//  Function类型

function sum(num1,num2) {
    return num1 + num2;
}

var sum = function(num1, num2) {
    return num1 + num2;
};

var sum = new Function("num1", "num2", "return num1+num2"); // 不推荐

//函数声明与函数表达式
alert(getSum(10, 10));
//函数声明
function getSum(num1,num2) {
    return num1 + num2;
}

// 函数表达式，执行期间将导致错误
alert(getSum(10, 10));
var getSum = function(num1, num2) {
    return num1 + num2;
};

// 作为值的函数

function callSomeFunction(someFunction,someArgument) {
    return someFunction(someArgument);
}

function add10(num) {
    return num + 10;
}

alert(callSomeFunction(add10, 10));

function createCompareFunction(propName) {
    return function(obj1, obj2) {
        var v1 = obj1[propName];
        var v2 = obj2[propName];
        if (v1 > v2) {
            return 1;
        }
        else if (v1 == v2) {
            return 0;
        }
        else {
            return -1;
        }
    };
}

var data = [{ name: "Nike", age: 24 }, { name: "Jack", age: 43}];
data.sort(createCompareFunction("name"));
alert(data[0].name); //Jack
data.sort(createCompareFunction("age"));
alert(data[0].name); //Nike

// 函数内部属性：arguments,this

function factorial(num) {
    if (num <= 1) {
        return 1;
    } else {
        return factorial(num - 1);
    }
}

//arguments的callee属性，指向拥有这个arguments对象的函数
function factorial(num) {
    if (num <= 1) {
        return 1;
    } else {
        return arguments.callee(num - 1);
    }
}

// this引用的是函数据以执行的环境对象
window.color = "red";
var o = { color: "blue" };

function sayColor() {
    alert(this.color);
}

sayColor(); // red
o.sayColor = sayColor;
o.sayColor(); //blue

// 函数属性和方法：length，prototype
//length：表示函数希望接收的命名参数的个数

function sayName(name) {
    return name;
}

function sum(n1,n2) {
    return n1 + n2;
}

function doSome() {
    alert('');
}

alert(sayName.length); //1
alert(sum.length); //2
alert(doSome.length); //0

//apply(),call():在特定作用域中调用函数
function sum(n1, n2) {
    return n1 + n2;
}

function callSum1(n1, n2) {
    return sum.apply(this, arguments);
}

function callSum2(n1, n2) {
    return sum.apply(this, [n1,n2]);
}

function callSum3(n1, n2) {
    return sum.call(this, n1,n2);
}

alert(callSum1(10, 10)); //20
alert(callSum2(10, 10)); //20
alert(callSum3(10, 10)); //20

window.color = "red";
var o = { color: "blue" };

function sayColor() {
    alert(this.color);
}

sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
//bind():创建一个函数的实例，其this值会被绑到传给bind函数的值
window.color = "red";
var o = { color: "blue" };

function sayColor() {
    alert(this.color);
}

var newFunc = sayColor.bind(o);
newFunc(); //blue

// 
var num1 = 10;
alert(num1.toFixed(2)); //10.00

var num2 = 10.005;
alert(num2.toFixed(2)); //10.01
alert(num1.toExponential(1)); // 1.0e+1

var num3 = 99;
alert(num3.toPrecision(1)); //1e+2
alert(num3.toPrecision(2)); //99
alert(num3.toPrecision(3)); //99.0

//
var strValue = "hello world";
alert(strValue.charAt(1)); //e
alert(strValue.charCodeAt(1)); //101
alert(strValue[1]); //e

alert(strValue.concat(" bye")); //hello world bye
alert(strValue.concat(" bye", " bye")); //hello world bye bye

alert(strValue.slice(3)); //lo world
alert(strValue.substring(3)); //lo world
alert(strValue.substr(3)); //lo world

alert(strValue.slice(3, 7)); //lo w
alert(strValue.substring(3, 7)); //lo w
alert(strValue.substr(3, 7)); //lo worl // 7：指定要返回的字符个数为7

// 字符串模式匹配
var text = "cat,bat,sat,fat";
var pattern = /.at/;

var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //cat
alert(matches.lastIndex); //0

alert(text.search(/at/)); //1

alert(text.replace("at", "ond")); //cond,bat,sat,fat
alert(text.replace("/at/g", "ond")); //cond,bond,sond,fond

//localeCompare():比较字符串大小

//fromCharCode()方法
alert(String.fromCharCode(104, 101, 108, 108, 111)); //hello

//单体内置对象Global，Math
//URI编码
//encodeURI主要用于整个URI（eg. http://www.wrox.com/illegal value.htm）而encodeURIComponent()主要用于对URI中的某一段(例如前面URI中的illegal value.htm)进行编码
//它们的主要区别在于，encodeURI不会对本身属于URI的特殊字符进行编码，例如冒号、正斜杠、问好和井号；而后者则会对它发现的任何非标准字符进行编码
var uri = "http://www.wrox.com/illegal value.htm#start";
alert(encodeURI(uri)); //http://www.wrox.com/illegal%20value.htm#start
alert(encodeURIComponent(uri)); //http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start

var enURI = "http://www.wrox.com/illegal%20value.htm#start";
alert(decodeURI(enURI)); //http://www.wrox.com/illegal value.htm#start
var enCURI = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start";
alert(decodeURIComponent(enCURI)); //http://www.wrox.com/illegal value.htm#start

//eval()：是一个完整的ECMAScript解析器
eval('alert("hello")'); //等同于 alert("hello");

var msg = "hello nick";
eval("alert(msg)"); // hello nick

eval("function sayHi(){alert('hi');}");
sayHi();

eval("var msg = 'hello kitty';");
alert(msg);

//Math对象
//min() max()方法
var max = Math.max(23, 2, 121, 43, 5); //121
var min = Math.min(2, 3, 4, 5, 6); //2

var values = [1, 2, 3, 4, 5, 6, 7, 8];
var max = Math.max.apply(Math, values); //8

//舍入方法 Math.ceil() Math.floor() Math.round()
Math.ceil(25.6);//26
Math.ceil(25.1);//26
Math.ceil(25.9);//26

Math.floor(25.6);//25
Math.floor(25.1);//25
Math.floor(25.9);//25

Math.round(25.6);//26
Math.round(25.1);//25
Math.round(25.9); //26

//random():返回0-1之间的一个随机数，不包括0和1
//从某个整数范围内随机选择一个值公式：值=Math.floor(Math.random()*可能值的总数+第一个可能的值)

//0-10
var r = Math.floor(Math.random() * 10 + 1);
// 2-10
var rr = Math.floor(Math.random() * 9 + 2);

function selectFrom(lower,upper) {
    var c = upper - lower + 1;
    return Math.floor(Math.random() * c + lower);
}

alert(selectFrom(2, 10));//包括2和10
var colors = ["red", "green", "blue", "orange"];
alert(colors[selectFrom(0, colors.length - 1)]);








